﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace YiJing.Model
{
    public sealed class WordWithSymbol
    {
        public string Text { get; set; }
        public string Symbol { get; set; }
    }

    public sealed class TrigramFigure : LineFigure
    {
        private static readonly Metadata[] Lookup =
            new[]
            {
                new Metadata // 000
                {
                    Name = new WordWithSymbol { Text = "kūn", Symbol = "坤"},
                    Animal = new WordWithSymbol { Text = "cow", Symbol = "牛"},
                    Nature = new WordWithSymbol { Text = "earth", Symbol = "地"},
                    Translation = "the Receptive, Field",
                    Direction = "southwest",
                    BodyPart = "belly",
                    Attribute = "devoted, yielding",
                    State = "receptive"
                },

                new Metadata // 001
                {
                    Name = new WordWithSymbol { Text = "gèn", Symbol = "艮"},
                    Animal = new WordWithSymbol { Text = "wolf, dog", Symbol = "狗"},
                    Nature = new WordWithSymbol { Text = "mountain", Symbol = "山"},
                    Translation = "Keeping Still, Bound",
                    Direction = "northeast",
                    BodyPart = "hand",
                    Attribute = "resting, stand-still",
                    State = "completion"
                },

                new Metadata // 010
                {
                    Name = new WordWithSymbol { Text = "kǎn", Symbol = "坎"},
                    Animal = new WordWithSymbol { Text = "pig", Symbol = "豕"},
                    Nature = new WordWithSymbol { Text = "water", Symbol = "水"},
                    Translation = "the Abysmal, Gorge",
                    Direction = "north",
                    BodyPart = "ear",
                    Attribute = "dangerous",
                    State = "in-motion"
                },

                new Metadata // 011
                {
                    Name = new WordWithSymbol { Text = "xùn", Symbol = "巽"},
                    Animal = new WordWithSymbol { Text = "fowl", Symbol = "雞"},
                    Nature = new WordWithSymbol { Text = "wind", Symbol = "風"},
                    Translation = "the Gentle, Ground",
                    Direction = "southeast",
                    BodyPart = "thigh",
                    Attribute = "penetrating",
                    State = "gentle entrance"
                },

                new Metadata // 100
                {
                    Name = new WordWithSymbol { Text = "zhèn", Symbol = "震"},
                    Animal = new WordWithSymbol { Text = "dragon", Symbol = "龍"},
                    Nature = new WordWithSymbol { Text = "thunder", Symbol = "雷"},
                    Translation = "the Arousing, Shake",
                    Direction = "east",
                    BodyPart = "foot",
                    Attribute = "inciting movement",
                    State = "initiative"
                },

                new Metadata // 101
                {
                    Name = new WordWithSymbol { Text = "lí", Symbol = "離"},
                    Animal = new WordWithSymbol { Text = "pheasant", Symbol = "雉"},
                    Nature = new WordWithSymbol { Text = "fire", Symbol = "火"},
                    Translation = "the Clinging, Radiance",
                    Direction = "south",
                    BodyPart = "eye",
                    Attribute = "light-giving, dependence",
                    State = "clinging, clarity, adaptable"
                },

                new Metadata // 110
                {
                    Name = new WordWithSymbol { Text = "duì", Symbol = "兌"},
                    Animal = new WordWithSymbol { Text = "sheep", Symbol = "羊"},
                    Nature = new WordWithSymbol { Text = "swamp, marsh", Symbol = "澤"},
                    Translation = "the Joyous, Open",
                    Direction = "west",
                    BodyPart = "mouth",
                    Attribute = "pleasure",
                    State = "tranquil (complete devotion)"
                },

                new Metadata // 111
                {
                    Name = new WordWithSymbol { Text = "qián", Symbol = "乾"},
                    Animal = new WordWithSymbol { Text = "horse", Symbol = "馬"},
                    Nature = new WordWithSymbol { Text = "heaven, sky", Symbol = "天"},
                    Translation = "the Creative, Force",
                    Direction = "northwest",
                    BodyPart = "head",
                    Attribute = "strong",
                    State = "creative"
                },
            };

        public const int MaxLines = 3;

        public sealed class Metadata
        {
            public WordWithSymbol Name { get; set; }
            public WordWithSymbol Nature { get; set; }
            public WordWithSymbol Animal { get; set; }
            public string Translation { get; set; }
            public string Direction { get; set; }
            public string BodyPart { get; set; }
            public string Attribute { get; set; }
            public string State { get; set; }
        }

        public TrigramFigure(IEnumerable<Line> bottomUpSequence) : base(bottomUpSequence, MaxLines)
        {
        }

        public int Value
        {
            get { return Lines.Reverse().Aggregate(0, (result, line) => (result << 1) + (line.IsBroken ? 0 : 1)); }
        }

        public Metadata Details
        {
            get { return Lookup[Value]; }
        }

        public static TrigramFigure FromValue(int index)
        {
            Guard.Against<ArgumentOutOfRangeException>(index < 0 || index > 7, "index");

            var result = new Line[MaxLines];

            for (var i = 0; i < MaxLines; ++i, index >>= 1)
                result[i] = new Line { IsBroken = (index & 1) == 0 };

            return new TrigramFigure(result);
        }
    }
}
